<template>
  <div class="YUploadVideo">
    <ul class="el-upload-list el-upload-list--picture-card">
      <li
        v-for="file in videoList"
        :key="file.id"
        class="el-upload-list__item">
        <img
          v-if="file.url"
          class="el-upload-list__item-thumbnail"
          :src="file.url" alt=""
        >
        <i v-else class="el-icon-loading"></i>
        <span class="el-upload-list__item-actions">
          <template v-if="file.videoUrl">
            <span
              class="el-upload-list__item-preview"
              @click="handlePreview(file)">
              <i class="el-icon-video-play"></i>
            </span>
            <template v-if="!disabled">
              <span
                v-if="reUpload"
                class="el-upload-list__item-delete"
                @click="handleEdit(file)">
                <i class="el-icon-upload2"></i>
              </span>
              <span
                class="el-upload-list__item-delete"
                @click="handleRemove(file)">
                <i class="el-icon-delete"></i>
              </span>
            </template>
          </template>
        </span>
      </li>
    </ul>
    <el-upload
      ref="yUpload"
      action=""
      :show-file-list="false"
      :file-list="videoList"
      :http-request="doUpload"
      :on-change="onChange"
      list-type="picture-card"
      :limit="limit"
      :class="{'max-pic': maxPic}"
      accept="video/mp4,video/ogg,video/webm"
      :auto-upload="false">
      <template slot="default">
        <i class="el-icon-plus"></i>
        <div v-if="showTip" class="el-upload__tip">只能上传mp4文件，且不超过{{limitSize}}mb</div>
      </template>
    </el-upload>
    <el-upload
      ref="yUpload2"
      style="display: none"
      action=""
      :file-list="editParam.videoList"
      list-type="picture-card"
      :on-change="onChange2"
      :show-file-list="false"
      :http-request="doUpload"
      accept="video/mp4,video/ogg,video/webm"
      :auto-upload="false">
      <el-button ref="editUpload"></el-button>
    </el-upload>
    <el-dialog
      :visible.sync="previewVisible"
      @closed="closePreview"
      append-to-body>
      <video v-if="displayFile"
         :src="displayFile.videoUrl" controls autoplay style="width: 100%; max-height: 80vh;"></video>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "YUploadVideo",
  inject: ['File2ArrayBuffer', 'generateMediaUrl', 'defaultUploadChange'],
  props:{
    disabled:{
      type: Boolean,
      default: false
    },
    limit:{
      type: Number,
      default: Infinity
    },
    showTip:{
      type: Boolean,
      default: true
    },
    limitSize:{
      type: Number,
      default: 10
    },
    businessSysModuleCode: String,
    url:{},
    model:{
      type: Object
    },
    reUpload:{
      type: Boolean,
      default: false
    },
    redrawOnServer:{//是否在图片保存/删除走接口之后才重绘页面，默认为false
      type: Boolean,
      default: false
    }
  },
  computed:{
    maxPic(){
      return this.videoList.length >= this.limit || this.disabled;
    },
    isVideoNull(){
      return !this.videoList.length
    }
  },
  data(){
    return{
      videoList: [],
      displayFile: null,
      previewVisible: false,
      updateLock: false,
      editParam:{
        videoList: [],
        currentFile: null
      },
      base64Cache:{//base64缓存

      }
    }
  },
  mounted(){
  },
  methods:{
    resetUrl(){
      this.$set(this, 'videoList', []);
      if(this.url){
        this.videoList = (new Array(this.url.length)).fill({});
        this.url.map(async (u, i) => {
          this.$set(this.videoList, i, {
            videoUrl: this.generateMediaUrl({
              fileOpenUrl: u.url
            }),
            url: await this.getVideoImgBlob(this.generateMediaUrl({
              fileOpenUrl: u.url
            })),
            name: u.url,
            id: u.id
          });
        })
      }
    },
    doUpload(){

    },
    handlePreview(file){
      this.displayFile = file;
      this.previewVisible = true;
    },
    closePreview(){
      //this.displayFile = null;
    },
    handleEdit(file){
      this.editParam.currentFile = file;
      this.$refs['editUpload'].$el.click();
    },
    // 上传按钮
    async onChange(fileObj, fileList) {
      if(!fileObj.name.endsWith('mp4') && !fileObj.name.endsWith('MP4')){
        this.$message({
          type: 'warning',
          message: `仅支持上传mp4格式的视频`
        });
        this.$refs['yUpload'].clearFiles();
        return;
      }
      if(fileObj.size > this.limitSize * 1024 * 1024){
        this.$message({
          type: 'warning',
          message: `文件大小超出限制：${this.limitSize}mb`
        });
        this.$refs['yUpload'].clearFiles();
        return;
      }
      this.defaultUploadChange(fileObj, async info => {
        let newVideo = {
          id: info.id,
          uid: fileObj.uid,
          url: await this.getVideoImgBlob(this.generateMediaUrl(info)),
          name: info.fileOpenUrl,
          videoUrl: this.generateMediaUrl(info)
        };
        if(this.redrawOnServer){
          this.$nextTick(() => {
            this.$bus.$once('redraw', bool => {
              bool && this.videoList.push(newVideo);
            })
          })
        }else{
          this.videoList.push(newVideo);
        }
        this.updateLock = true;
        this.$nextTick(() => {
          this.$emit("update", {
            type: 'add',
            file: {
              id: newVideo.id,
              url: newVideo.videoUrl,
              name: newVideo.name
            }
          });
        })
      }, e => {
        this.$set(this, 'videoList', [...this.videoList]);
      });
    },
    onChange2(fileObj){
      if(!fileObj.name.endsWith('mp4') && !fileObj.name.endsWith('MP4')){
        this.$message({
          type: 'warning',
          message: `仅支持上传mp4格式的视频`
        });
        this.$refs['yUpload2'].clearFiles();
        return;
      }
      if(fileObj.size > this.limitSize * 1024 * 1024){
        this.$message({
          type: 'warning',
          message: `文件大小超出限制：${this.limitSize}mb`
        });
        this.$refs['yUpload2'].clearFiles();
        return;
      }
      this.defaultUploadChange(fileObj, async info => {
        let newVideo = {
          id: info.id,
          uid: fileObj.uid,
          url: await this.getVideoImgBlob(this.generateMediaUrl(info)),
          name: info.fileOpenUrl,
          videoUrl: this.generateMediaUrl(info)
        };
        let oldFile = {...this.editParam.currentFile}
        if(this.redrawOnServer){
          this.$nextTick(() => {
            this.$bus.$once('redraw', bool => {
              bool && Object.assign(this.editParam.currentFile, newVideo);
            })
          })
        }else{
          Object.assign(this.editParam.currentFile, newVideo);
        }
        this.updateLock = true;
        this.$nextTick(() => {
          this.$emit("update", {
            type: 'edit',
            file: {
              id: newVideo.id,
              url: newVideo.videoUrl,
              name: newVideo.name
            },
            preFile: oldFile
          });
          //这里手动gc一下
          this.$set(this.editParam, 'videoList', []);
        })
      }, e => {
        this.$set(this, 'videoList', [...this.videoList]);
      });
    },
    handleRemove(file, fileList){
      let delFile = {...file};
      let delIndex = this.videoList.findIndex(f => f.uid === file.uid);
      let delId = this.videoList[delIndex].id;
      if(this.redrawOnServer){
        this.$nextTick(() => {
          this.$bus.$once('redraw', bool => {
            bool && delIndex >= 0 && this.$delete(this.videoList, delIndex);
          })
        })
      }else{
        delIndex >= 0 && this.$delete(this.videoList, delIndex);
      }
      delId && this.$yAxios({
        url: this.$api.common.removeAttachment,
        data:{
          id: delId
        }
      })
      this.updateLock = true;
      this.$nextTick(() => {
        this.$emit("update", {
          type: 'delete',
          file: {
            id: delFile.id,
            url: delFile.videoUrl,
            name: delFile.name
          }
        });
      })
    },
    getVideoImgBlob(url) {
      let _this = this;
      return new Promise(function (resolve, reject) {
        if(_this.base64Cache[url]){
          resolve(_this.base64Cache[url]);
        }else{
          try{
            let scale = 0.8; //第一帧图片与原视频比例
            let video = document.createElement("video");
            video.setAttribute('crossOrigin', 'anonymous');//处理跨域
            video.setAttribute('src', url);
            video.currentTime = 3;
            video.addEventListener('canplay', function () {
              let canvas = document.createElement("canvas");
              canvas.width = video.videoWidth*scale;
              canvas.height = video.videoHeight*scale;
              canvas.getContext("2d").drawImage(video, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height); //绘制canvas
              let base64 =  canvas.toDataURL('image/png')/*.replace('image/png', 'image/octet-stream')*/;
              _this.base64Cache[url] = base64
              resolve(base64);
            });
          }catch(e){
            this.$message({
              type: 'danger',
              message: e.message || '加载视频失败'
            })
            resolve('');
          }
        }
      })
    }
  },
  watch:{
    url:{
      handler(newVal, oldVal){
        if(this.updateLock) this.updateLock = false;
        else{
          JSON.stringify(newVal) !== JSON.stringify(oldVal) && this.resetUrl();
        }
      },
      immediate: true
    }
  }
}
</script>

<style scoped lang="less">
.YUploadVideo{
  display: inline-block;
  min-height: 148px;
  >.el-upload-list{
    & +div{
      display: inline-block;
    }
  }
  /deep/.el-upload{
    position: relative;
    .el-upload-dragger{
      width: 100%;
      height: 100%;
    }
    .el-upload__tip{
      position: absolute;
      bottom: 0;
      line-height: normal;
      padding: 0 10px;
    }
  }
  /deep/.el-upload-list__item{
    margin: 0;
    transition: none!important;
    text-align: center;
    >i{
      display: inline-block;
      position: relative;
      width: 48px;
      height: 48px;
      font-size: 48px;
      top: 48px;
    }
  }
  /deep/.max-pic{
    .el-upload{
      display: none;
    }
  }
}
</style>